<?php


namespace Drupal\shushengyuan\Traits;


use Drupal\commerce_weight_shipping\Entity\CommerceWeightShipping;
use Drupal\s_store_order\Entity\SStoreOrder;
use Drupal\shusy_errand\Entity\ShusyErrand;
use Drupal\shusy_product\Entity\ShusyProductStandard;
use Drupal\shusy_product_s_cost\Entity\ShusyProductSCost;
use Drupal\shusy_store\Entity\ShusyStore;
use Drupal\shusy_store_order\Entity\ShusyStoreOrder;
use Drupal\shusy_store_order_address\Entity\ShusyStoreOrderAddress;
use Drupal\shusy_store_order_line\Entity\ShusyStoreOrderLine;
use Drupal\shusy_store_order_shipping\Entity\ShusyStoreOrderShipping;
use Drupal\shusy_store_order_validity\Entity\ShusyStoreOrderValidity;
use Drupal\store\Entity\Store;
use EntityListWrapper;
use ServicesException;

trait ServicesControllerTrait {

  /**
   * @var \EasyWeChat\MiniProgram\Application
   */
  protected $mini;

  /**
   * @var \EasyWeChat\OfficialAccount\Application
   */
  protected $official;

  function __construct() {
    if (module_exists('wx_mini_program')) {
      $this->mini = wx_mini_program_get_app();
    }
    if (module_exists('wx_official_account')) {
      $this->official = wx_official_account_get_app();
    }
    return $this;
  }

  /**
   * @param \Drupal\shusy_product\Entity\ShusyProductStandard $standard
   * @param int $uid
   * @return false|float
   * @deprecated
   */
  protected function getVipPrice(ShusyProductStandard $standard, int $uid) {
    $standardWrapper = $standard->wrapper();
    $cost = $standard->amount;
    $amount = $cost * shushengyuan_get_discount($uid);;
    return ceil($amount);
  }

  protected function getOpenId() {
    global $user;
    return $user->openid;
  }

  /**
   * @param $myLat
   * @param $myLng
   * @param $distance int km
   * @return array|float
   */
  protected function getRange($myLat, $myLng, $distance) {
    //以下为核心代码
    $range = 180 / pi() * $distance / 6378.137; //里面的 1 就代表搜索 1km 之内，单位km
    $lngR = $range / cos($myLat * pi() / 180);
    $maxLat = $myLat + $range; //最大纬度
    $minLat = $myLat - $range; //最小纬度
    $maxLng = $myLng + $lngR; //最大经度
    $minLng = $myLng - $lngR; //最小经度
    $range = [
      'minLat' => $minLat,
      'maxLat' => $maxLat,
      'minLon' => $minLng,
      'maxLon' => $maxLng,
    ];
    return $range;
  }

  /**
   * @param $lat1
   * @param $lng1
   * @param $lat2
   * @param $lng2
   * @return float
   * 获取2点之间的距离 km
   */
  protected function getDistance($lat1, $lng1, $lat2, $lng2) {
    //将角度转为狐度
    $radLat1 = deg2rad($lat1);//deg2rad()函数将角度转换为弧度
    $radLat2 = deg2rad($lat2);
    $radLng1 = deg2rad($lng1);
    $radLng2 = deg2rad($lng2);
    $a = $radLat1 - $radLat2;
    $b = $radLng1 - $radLng2;
    $s = 2 * asin(sqrt(pow(sin($a / 2), 2) + cos($radLat1) * cos($radLat2) * pow(sin($b / 2), 2))) * 6378.137;
    return $s;
  }

  protected function filePrepareDirectory($entity_type, $field_name, $bundle_name) {
    $info_instance = field_info_instance($entity_type, $field_name, $bundle_name);
    $info_field = field_info_field($field_name);
    $dir = file_field_widget_uri($info_field, $info_instance);
    $result = file_prepare_directory($dir);
    if (empty($result)) {
      drupal_mkdir($dir, 0777, TRUE);
    }
    return $dir;
  }

  /**
   * @return bool|ShusyStore
   * @throws \ServicesException
   */
  protected function getStore() {
    $store = $this->getStoreNoException();
    if ($store instanceof ShusyStore) {
      return $store;
    }
    throw new ServicesException('未申请商家入驻或未审核通过');
  }

  protected function getStoreNoException() {
    $uid = $this->getUid();
    $es = shusy_store_load_multiple(FALSE, ['uid' => $uid]);
    if (!empty($es)) {
      $e = reset($es);
      if ($e instanceof ShusyStore && $e->status == 1) {
        return $e;
      }
    }
    return FALSE;
  }

  protected function getUid() {
    global $user;
    return $user->uid;
  }

  protected function convertYuan($amount) {
    return ($amount / 100) + 0;
  }

  protected function formatDate($timestamp, $format) {
    return format_date($timestamp, 'custom', $format);
  }

  /**
   * @return \Drupal\shusy_errand\Entity\ShusyErrand|bool
   */
  protected function getErrand() {
    $es = shusy_errand_load_multiple(FALSE, ['uid' => $this->getUid()]);
    if (!empty($es)) {
      $e = reset($es);
      if ($e instanceof ShusyErrand && $e->status == 1) {
        return $e;
      }
    }
    return FALSE;
  }

  /**
   * @param $uid
   * @return bool|\Drupal\shusy_city\Entity\ShusyCity
   * 返回 uid 所在城市
   */
  protected function getCity($uid) {
    $cache = cache_get("in_city_{$uid}", 'cache_shushengyuan');
    if (!empty($cache) && $cache->expire >= REQUEST_TIME) {
      return shusy_city_load($cache->data);
    }
    return FALSE;
  }

  /**
   * @param int $order_id
   * @return bool|Store
   */
  protected function getStoreByOrderId(int $order_id) {
    $es = entity_load('s_store_order', FALSE, ['order_id' => $order_id]);
    if (!empty($es)) {
      $e = reset($es);
      if ($e instanceof SStoreOrder) {
        return store_load($e->store_id);
      }
    }
    return FALSE;
  }

  protected function cacheGet($cid, bool $autoDel = FALSE) {
    $cache = cache_get($cid, 'cache_shushengyuan');
    if (!empty($cache) && $autoDel) {
      $this->cacheDel($cid);
    }
    return $cache;
  }

  protected function cacheDel($cid) {
    cache_clear_all($cid, 'cache_shushengyuan');
  }

  protected function cacheSet($cid, $data, $expire = CACHE_PERMANENT) {
    return cache_set($cid, $data, 'cache_shushengyuan', $expire);
  }

  protected function cacheClear($cid) {
    cache_clear_all($cid, 'cache_shushengyuan');
  }

  protected function imageStyleUrl($style_name, $uri) {
    $name = strtolower($style_name);
    $styles = image_styles();
    if (!isset($styles[$name])) {
      image_style_save([
        'name' => $name,
        'label' => $style_name,
      ]);
    }
    return image_style_url($name, $this->getUri($uri));
  }

  private function getUri($uri) {
    if (is_string($uri)) {
      return $uri;
    }
    if (is_array($uri) && isset($uri['uri'])) {
      return $uri['uri'];
    }
    if (is_object($uri) && isset($uri->uri)) {
      return $uri->uri;
    }
    return '';
  }

  //预处理 offset 前端认为是 page 按page 逻辑处理数据
  protected function preprocessOffset(int &$offset, int &$limit) {

  }

  protected function isDev() {
    if (variable_get_value('wx_mini_program:mini:dev')) {
      return TRUE;
    }
    return FALSE;
  }

  protected function refreshOrderValidity(int $id) {
    $es = shusy_store_order_validity_load_multiple(FALSE, ['store_order_id' => $id]);
    if (!empty($es)) {
      $e = reset($es);
    }
    else {
      $e = new ShusyStoreOrderValidity();
      $e->store_order_id = $id;
    }
    if ($e instanceof ShusyStoreOrderValidity) {
      //有效期24小时
      $e->validity = REQUEST_TIME + (0.5 * 60 * 60);
      $e->save();
    }
  }

  protected function watchdog($type, $message, $variables = [], $severity = WATCHDOG_NOTICE, $link = NULL) {
    if ($this->isDev()) {
      watchdog($type, $message, $variables, $severity, $link);
    }
  }

  protected function switchShipping(int $id, int $shipping) {
    $uid = $this->getUid();
    $order = shusy_store_order_load($id);
    if ($order instanceof ShusyStoreOrder && $order->uid == $uid) {
      //重新计算运费
      $this->clearShippingLine($order);
      //配送方式 0 到店自提 1 快达 2 快递
      switch ($shipping) {
        case 0:
          $line = new ShusyStoreOrderLine();
          $line->type = 'shipping';
          $line->store_order_id = $order->id;
          $line->name = '到店自提';
          $line->amount = 0;
          $line->qty = 1;
          $line->status = 1;
          $line->save();
          $lineProduct = new ShusyStoreOrderShipping();
          $lineProduct->store_order_line_id = $line->id;
          $lineProduct->shipping_type = 'shusy_service';
          $lineProduct->save();
          break;
        case 1:
          $line = new ShusyStoreOrderLine();
          $line->type = 'shipping';
          $line->store_order_id = $order->id;
          $line->name = '快达';
          //固定15金额
          $line->amount = 1500;
          $line->qty = 1;
          $line->status = 1;
          $line->save();
          $lineProduct = new ShusyStoreOrderShipping();
          $lineProduct->store_order_line_id = $line->id;
          $lineProduct->shipping_type = 'shusy_errand';
          $lineProduct->save();
          break;
        case 2:
          //切换为快递时要看是否已选地址 如果有地址需要计算运费
          //检查对应店铺是否设置了邮费模板 如果没有设置则不能切换到快递
          $orderWrapper = $order->wrapper();
          $address = $orderWrapper->address->value();
          if ($address instanceof ShusyStoreOrderAddress) {
            $this->addressComputeShipping($address, $order);
          }
          else {
            throw new ApiException('请先选择地址');
          }
          break;
      }
      $order->save();
    }
  }

  protected function addressComputeShipping(ShusyStoreOrderAddress $address, ShusyStoreOrder $order) {
    //返回订单商品总重量 与 收货地址国家行政编码
    $shipping = FALSE;
    $national = $address->nationalcode;
    $weight = 0;
    $amount = 0;

    $orderWrapper = $order->wrapper();
    $commerce_line_items = $orderWrapper->lines;
    if ($commerce_line_items instanceof EntityListWrapper) {
      foreach ($commerce_line_items->getIterator() as $item) {
        if ($item->type->value() == 'product' && $item->status->value() == 1) {
          $scost = $item->standard->product->scost->value();
          if ($scost instanceof ShusyProductSCost) {
            $cost_type = $scost->cost_type;
            //计费方式 number 按件 weight 按重量
            switch ($cost_type) {
              case 'number':
                //按件计费的直接进行计算
                $qty = $item->qty->value();
                $amount += $scost->getAmount($qty);
                break;
              case 'weight':
                //按重量计费的进行累计
                //此处单位是克
                $weight += $item->standard->weight->value();
                break;
            }
          }
        }
      }
    }
    $es = commerce_weight_shipping_load_multiple(FALSE, [
      'status' => 1,
      'store_id' => $order->store_id,
    ]);
    if (!empty($es)) {
      $shipping = reset($es);
    }
    if ($shipping instanceof CommerceWeightShipping) {
      $amount += commerce_weight_shipping_callback_rate($shipping, ($weight / 1000), $national);
      $this->watchdog(__FUNCTION__, serialize([$amount, $weight, $national]));
      $line = new ShusyStoreOrderLine();
      $line->type = 'shipping';
      $line->store_order_id = $order->id;
      $line->amount = $amount;
      $line->qty = 1;
      $line->status = 1;
      $line->name = $shipping->title;
      $line->save();
      $lineProduct = new ShusyStoreOrderShipping();
      $lineProduct->store_order_line_id = $line->id;
      $lineProduct->shipping_type = 'commerce_weight_shipping';
      $lineProduct->save();
    }
  }

  protected function getLoginOptions($name) {
    $headers = $this->getHeaders();
    //Services-Login-Options
    $json = $headers['Services-Login-Options'] ?? "{}";
    $result = drupal_json_decode($json);
    return $result[$name] ?? '';
  }

  protected function getSpreadVars() {
    $spread_type = 0;
    if (!empty($this->getLoginOptions('room_id'))) {
      $spread_type = 1;
    }
    $spread_anchor_uid = 0;
    $custom_params = $this->getLoginOptions('custom_params');
    if (!empty($custom_params)) {
      $custom_params = drupal_json_decode(urldecode($custom_params));
      $spread_anchor_uid = $custom_params['uid'] ?? 0;
    }
    return [$spread_type, $spread_anchor_uid];
  }

  protected function getHeaders() {
    if (function_exists('apache_request_headers')) {
      // we need this to get the actual Authorization: header
      // because apache tends to tell us it doesn't exist
      $headers = apache_request_headers();

      // sanitize the output of apache_request_headers because
      // we always want the keys to be Cased-Like-This and arh()
      // returns the headers in the same case as they are in the
      // request
      $out = [];
      foreach ($headers as $key => $value) {
        $key = str_replace(" ", "-", ucwords(strtolower(str_replace("-", " ", $key))));
        $out[$key] = $value;
      }
    }
    else {
      // otherwise we don't have apache and are just going to have to hope
      // that $_SERVER actually contains what we need
      $out = [];
      if (isset($_SERVER['CONTENT_TYPE'])) {
        $out['Content-Type'] = $_SERVER['CONTENT_TYPE'];
      }
      if (isset($_ENV['CONTENT_TYPE'])) {
        $out['Content-Type'] = $_ENV['CONTENT_TYPE'];
      }

      foreach ($_SERVER as $key => $value) {
        if (substr($key, 0, 5) == "HTTP_") {
          // this is chaos, basically it is just there to capitalize the first
          // letter of every word that is not an initial HTTP and strip HTTP
          // code from przemek
          $key = str_replace(" ", "-", ucwords(strtolower(str_replace("_", " ", substr($key, 5)))));
          $out[$key] = $value;
        }
      }
      // The "Authorization" header may get turned into "Auth".
      if (isset($out['Auth'])) {
        $out['Authorization'] = $out['Auth'];
      }
    }
    return $out;
  }

}

/**
 * @param $str
 * @return string
 * 覆盖使用 去掉不可见空白
 */
function trim($str) {
  return \trim($str, " \t\n\r\0\x0B\xC2\xA0");
}
